<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LangChain4J AI 聊天助手</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }

        :root {
            --primary-color: #4f46e5;
            --primary-light: #818cf8;
            --secondary-color: #7c3aed;
            --user-bg: #dbeafe;
            --ai-bg: #ede9fe;
            --light-bg: #f9fafb;
            --dark-bg: #1f2937;
            --text-light: #374151;
            --text-dark: #f9fafb;
            --card-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            --transition: all 0.3s ease;
        }

        .dark-mode {
            --primary-color: #818cf8;
            --primary-light: #a5b4fc;
            --secondary-color: #a78bfa;
            --user-bg: #1e3a8a;
            --ai-bg: #4c1d95;
            --light-bg: #111827;
            --dark-bg: #1f2937;
            --text-light: #f9fafb;
            --text-dark: #f9fafb;
            --card-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
        }

        body {
            background: linear-gradient(135deg, #f0f9ff, #e0f2fe);
            color: var(--text-light);
            transition: var(--transition);
            min-height: 100vh;
            display: flex;
            flex-direction: column;
        }

        .dark-mode body {
            background: linear-gradient(135deg, #0f172a, #1e293b);
        }

        header {
            background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
            color: white;
            padding: 1.5rem 2rem;
            display: flex;
            justify-content: space-between;
            align-items: center;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        }

        .logo-container {
            display: flex;
            align-items: center;
            gap: 1rem;
        }

        .logo {
            font-size: 1.8rem;
            font-weight: bold;
            display: flex;
            align-items: center;
            gap: 0.5rem;
        }

        .logo span {
            color: #ffde59;
        }

        .tagline {
            font-size: 0.9rem;
            opacity: 0.9;
            margin-top: 0.2rem;
        }

        .controls {
            display: flex;
            gap: 1rem;
            align-items: center;
        }

        .theme-toggle {
            background: rgba(255, 255, 255, 0.2);
            border: none;
            color: white;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: var(--transition);
        }

        .theme-toggle:hover {
            background: rgba(255, 255, 255, 0.3);
            transform: rotate(15deg);
        }

        .container {
            display: flex;
            flex: 1;
            max-width: 1400px;
            margin: 2rem auto;
            padding: 0 1.5rem;
            gap: 2rem;
            width: 100%;
        }

        .chat-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            background: rgba(255, 255, 255, 0.8);
            backdrop-filter: blur(10px);
            border-radius: 16px;
            box-shadow: var(--card-shadow);
            overflow: hidden;
            transition: var(--transition);
        }

        .dark-mode .chat-container {
            background: rgba(30, 41, 59, 0.8);
        }

        .chat-header {
            padding: 1.5rem;
            background: rgba(79, 70, 229, 0.1);
            border-bottom: 1px solid rgba(0, 0, 0, 0.05);
            display: flex;
            align-items: center;
            gap: 1rem;
        }

        .chat-icon {
            width: 48px;
            height: 48px;
            background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-size: 1.5rem;
        }

        .chat-title {
            font-size: 1.4rem;
            font-weight: 600;
        }

        .chat-subtitle {
            font-size: 0.9rem;
            opacity: 0.8;
            margin-top: 0.2rem;
        }

        .chat-history {
            flex: 1;
            padding: 1.5rem;
            overflow-y: auto;
            display: flex;
            flex-direction: column;
            gap: 1.5rem;
            min-height: 400px;
        }

        .message {
            max-width: 85%;
            padding: 1.25rem;
            border-radius: 16px;
            line-height: 1.5;
            box-shadow: var(--card-shadow);
            animation: fadeIn 0.3s ease;
            position: relative;
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        .user-message {
            background-color: var(--user-bg);
            align-self: flex-end;
            border-bottom-right-radius: 4px;
        }

        .ai-message {
            background-color: var(--ai-bg);
            align-self: flex-start;
            border-bottom-left-radius: 4px;
        }

        .message-header {
            display: flex;
            align-items: center;
            gap: 0.75rem;
            margin-bottom: 0.75rem;
            font-weight: 600;
        }

        .user-message .message-header {
            color: #1e40af;
        }

        .ai-message .message-header {
            color: #5b21b6;
        }

        .dark-mode .user-message .message-header {
            color: #93c5fd;
        }

        .dark-mode .ai-message .message-header {
            color: #c4b5fd;
        }

        .avatar {
            width: 36px;
            height: 36px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            color: white;
        }

        .user-avatar {
            background-color: var(--primary-color);
        }

        .ai-avatar {
            background-color: var(--secondary-color);
        }

        .message-content {
            line-height: 1.6;
        }

        .message-content pre {
            background: rgba(0, 0, 0, 0.05);
            padding: 0.75rem;
            border-radius: 8px;
            overflow-x: auto;
            margin-top: 0.5rem;
            font-family: 'Courier New', monospace;
        }

        .message-content code {
            background: rgba(0, 0, 0, 0.05);
            padding: 0.2rem 0.4rem;
            border-radius: 4px;
            font-family: 'Courier New', monospace;
        }

        .input-container {
            padding: 1.5rem;
            background: var(--light-bg);
            border-top: 1px solid rgba(0, 0, 0, 0.05);
        }

        .input-area {
            display: flex;
            gap: 1rem;
        }

        textarea {
            flex: 1;
            padding: 1rem 1.25rem;
            border: 1px solid #d1d5db;
            border-radius: 12px;
            resize: none;
            height: 100px;
            font-size: 1rem;
            transition: var(--transition);
            background-color: var(--light-bg);
            color: var(--text-light);
        }

        textarea:focus {
            outline: none;
            border-color: var(--primary-color);
            box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2);
        }

        .send-button {
            background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
            color: white;
            border: none;
            border-radius: 12px;
            padding: 0 1.75rem;
            cursor: pointer;
            font-weight: 600;
            transition: var(--transition);
            display: flex;
            align-items: center;
            gap: 0.5rem;
            font-size: 1rem;
        }

        .send-button:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(79, 70, 229, 0.3);
        }

        .send-button:disabled {
            background: #9ca3af;
            cursor: not-allowed;
            transform: none;
            box-shadow: none;
        }

        .sidebar {
            width: 320px;
            display: flex;
            flex-direction: column;
            gap: 1.5rem;
        }

        .card {
            background: rgba(255, 255, 255, 0.8);
            backdrop-filter: blur(10px);
            border-radius: 16px;
            padding: 1.75rem;
            box-shadow: var(--card-shadow);
            transition: var(--transition);
        }

        .dark-mode .card {
            background: rgba(30, 41, 59, 0.8);
        }

        .card-title {
            font-size: 1.25rem;
            font-weight: 600;
            margin-bottom: 1.25rem;
            display: flex;
            align-items: center;
            gap: 0.75rem;
            color: var(--primary-color);
        }

        .model-info {
            display: flex;
            flex-direction: column;
            gap: 0.75rem;
        }

        .info-item {
            display: flex;
            justify-content: space-between;
            padding: 0.75rem 0;
            border-bottom: 1px solid rgba(0, 0, 0, 0.08);
        }

        .info-label {
            font-weight: 500;
            display: flex;
            align-items: center;
            gap: 0.5rem;
        }

        .info-value {
            font-weight: 600;
            color: var(--primary-color);
        }

        .action-buttons {
            display: flex;
            flex-direction: column;
            gap: 0.75rem;
        }

        .action-button {
            padding: 0.9rem 1.25rem;
            border-radius: 12px;
            border: 1px solid #d1d5db;
            background: transparent;
            display: flex;
            align-items: center;
            gap: 0.75rem;
            cursor: pointer;
            transition: var(--transition);
            color: var(--text-light);
            font-size: 1rem;
        }

        .action-button:hover {
            background-color: var(--primary-color);
            color: white;
            border-color: var(--primary-color);
            transform: translateY(-2px);
        }

        .examples {
            display: flex;
            flex-direction: column;
            gap: 0.75rem;
        }

        .example {
            padding: 1rem;
            background: rgba(79, 70, 229, 0.08);
            border-radius: 12px;
            cursor: pointer;
            transition: var(--transition);
            border-left: 3px solid var(--primary-color);
        }

        .example:hover {
            background: rgba(79, 70, 229, 0.15);
            transform: translateX(5px);
        }

        footer {
            text-align: center;
            padding: 1.5rem;
            color: var(--text-light);
            font-size: 0.9rem;
            background-color: rgba(255, 255, 255, 0.5);
            border-top: 1px solid rgba(0, 0, 0, 0.05);
            backdrop-filter: blur(10px);
        }

        .dark-mode footer {
            background-color: rgba(30, 41, 59, 0.5);
        }

        @media (max-width: 900px) {
            .container {
                flex-direction: column;
            }

            .sidebar {
                width: 100%;
            }

            .message {
                max-width: 90%;
            }
        }

        @media (max-width: 600px) {
            header {
                flex-direction: column;
                gap: 1rem;
                text-align: center;
            }

            .message {
                max-width: 100%;
            }
        }

        .typing-indicator {
            display: flex;
            align-items: center;
            gap: 0.5rem;
            padding: 1rem;
            background: var(--ai-bg);
            border-radius: 12px;
            align-self: flex-start;
            width: fit-content;
            margin-top: -0.5rem;
        }

        .typing-dot {
            width: 8px;
            height: 8px;
            background: var(--secondary-color);
            border-radius: 50%;
            animation: typingAnimation 1.4s infinite ease-in-out;
        }

        .typing-dot:nth-child(1) {
            animation-delay: 0s;
        }

        .typing-dot:nth-child(2) {
            animation-delay: 0.2s;
        }

        .typing-dot:nth-child(3) {
            animation-delay: 0.4s;
        }

        @keyframes typingAnimation {
            0%, 60%, 100% {
                transform: translateY(0);
            }
            30% {
                transform: translateY(-6px);
            }
        }

        .status-indicator {
            display: inline-flex;
            align-items: center;
            gap: 0.5rem;
            font-size: 0.85rem;
            padding: 0.25rem 0.75rem;
            border-radius: 999px;
            background: rgba(79, 70, 229, 0.1);
            color: var(--primary-color);
            margin-top: 0.5rem;
        }

        .status-dot {
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: var(--primary-color);
            animation: pulse 1.5s infinite;
        }

        @keyframes pulse {
            0% { opacity: 0.5; }
            50% { opacity: 1; }
            100% { opacity: 0.5; }
        }

        .powered-by {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 0.5rem;
            margin-top: 0.5rem;
            font-size: 0.85rem;
            opacity: 0.8;
        }
    </style>
</head>
<body>
    <header>
        <div class="logo-container">
            <i class="fas fa-robot fa-2x"></i>
            <div>
                <div class="logo">LangChain<span>4J</span> AI 助手</div>
                <div class="tagline">基于 Spring Boot 和 LangChain4J 技术构建的智能对话系统</div>
            </div>
        </div>
        <div class="controls">
            <button class="theme-toggle" id="themeToggle">
                <i class="fas fa-moon"></i>
            </button>
        </div>
    </header>

    <div class="container">
        <div class="chat-container">
            <div class="chat-header">
                <div class="chat-icon">
                    <i class="fas fa-comments"></i>
                </div>
                <div>
                    <div class="chat-title">AI 对话助手</div>
                    <div class="chat-subtitle">输入问题，获取 LangChain4J 的智能回答</div>
                </div>
            </div>

            <div class="chat-history" id="chatHistory">
                <div class="message ai-message">
                    <div class="message-header">
                        <div class="avatar ai-avatar"><i class="fas fa-robot"></i></div>
                        <div>LangChain4J 助手</div>
                    </div>
                    <div class="message-content">
                        您好！我是基于 LangChain4J 和 Spring Boot 构建的AI助手。您可以向我提问任何问题，我会尽力提供准确和有用的回答。
                        <div class="status-indicator" id="connectionStatus">
                            <div class="status-dot"></div>
                            <span>已连接到后端服务</span>
                        </div>
                    </div>
                </div>

                <div class="typing-indicator" id="typingIndicator" style="display: none;">
                    <div class="typing-dot"></div>
                    <div class="typing-dot"></div>
                    <div class="typing-dot"></div>
                    <span>正在思考...</span>
                </div>
            </div>

            <div class="input-container">
                <div class="input-area">
                    <textarea id="userInput" placeholder="输入您的问题，例如：如何在Spring Boot中集成LangChain4J？"></textarea>
                    <button class="send-button" id="sendButton">
                        <i class="fas fa-paper-plane"></i> 发送
                    </button>
                </div>
                <div class="powered-by">
                    <span>技术栈：</span>
                    <span>Spring Boot</span>
                    <i class="fas fa-circle"></i>
                    <span>LangChain4J</span>
                    <i class="fas fa-circle"></i>
                    <span>Java AI</span>
                </div>
            </div>
        </div>

        <div class="sidebar">
            <div class="card">
                <div class="card-title">
                    <i class="fas fa-microchip"></i>
                    <span>模型信息</span>
                </div>
                <div class="model-info">
                    <div class="info-item">
                        <span class="info-label"><i class="fas fa-brain"></i> 模型名称:</span>
                        <span class="info-value">gpt-4-turbo</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label"><i class="fas fa-layer-group"></i> 上下文长度:</span>
                        <span class="info-value">128K tokens</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label"><i class="fas fa-calendar-alt"></i> 知识截止:</span>
                        <span class="info-value">2024年4月</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label"><i class="fas fa-ruler"></i> 最大响应:</span>
                        <span class="info-value">4096 tokens</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label"><i class="fas fa-bolt"></i> 响应速度:</span>
                        <span class="info-value">快速</span>
                    </div>
                </div>
            </div>

            <div class="card">
                <div class="card-title">
                    <i class="fas fa-cogs"></i>
                    <span>操作面板</span>
                </div>
                <div class="action-buttons">
                    <button class="action-button" id="clearHistory">
                        <i class="fas fa-trash-alt"></i> 清除对话历史
                    </button>
                    <button class="action-button">
                        <i class="fas fa-file-export"></i> 导出对话记录
                    </button>
                    <button class="action-button">
                        <i class="fas fa-history"></i> 查看历史对话
                    </button>
                </div>
            </div>

            <div class="card">
                <div class="card-title">
                    <i class="fas fa-lightbulb"></i>
                    <span>示例问题</span>
                </div>
                <div class="examples">
                    <div class="example" onclick="setExample(this)">如何在Spring Boot中集成LangChain4J？</div>
                    <div class="example" onclick="setExample(this)">LangChain4J支持哪些向量数据库？</div>
                    <div class="example" onclick="setExample(this)">请用Java写一个LangChain4J的示例代码</div>
                    <div class="example" onclick="setExample(this)">解释LangChain4J中的Agent概念</div>
                    <div class="example" onclick="setExample(this)">LangChain4J有哪些记忆管理功能？</div>
                </div>
            </div>
        </div>
    </div>

    <footer>
        <p>© 2023 LangChain4J Spring Boot 集成 | 使用AI技术增强您的应用程序</p>
    </footer>

    <script>
        // 主题切换功能
        const themeToggle = document.getElementById('themeToggle');
        const body = document.body;

        themeToggle.addEventListener('click', () => {
            body.classList.toggle('dark-mode');
            const icon = themeToggle.querySelector('i');
            if (body.classList.contains('dark-mode')) {
                icon.classList.replace('fa-moon', 'fa-sun');
                document.querySelector('header').style.background = 'linear-gradient(135deg, #3730a3, #5b21b6)';
            } else {
                icon.classList.replace('fa-sun', 'fa-moon');
                document.querySelector('header').style.background = 'linear-gradient(135deg, #4f46e5, #7c3aed)';
            }
        });

        // DOM元素引用
        const userInput = document.getElementById('userInput');
        const sendButton = document.getElementById('sendButton');
        const chatHistory = document.getElementById('chatHistory');
        const typingIndicator = document.getElementById('typingIndicator');
        const clearHistoryBtn = document.getElementById('clearHistory');
        const connectionStatus = document.getElementById('connectionStatus');

        // 当前对话状态
        let isWaitingForResponse = false;
        let currentAiMessage = null;

        // 发送消息功能
        sendButton.addEventListener('click', sendMessage);
        userInput.addEventListener('keydown', (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendMessage();
            }
        });

        // 清除历史功能
        clearHistoryBtn.addEventListener('click', () => {
            chatHistory.innerHTML = `
                <div class="message ai-message">
                    <div class="message-header">
                        <div class="avatar ai-avatar"><i class="fas fa-robot"></i></div>
                        <div>LangChain4J 助手</div>
                    </div>
                    <div class="message-content">
                        对话历史已清除。请问我任何问题，我会尽力为您提供帮助！
                        <div class="status-indicator" id="connectionStatus">
                            <div class="status-dot"></div>
                            <span>已连接到后端服务</span>
                        </div>
                    </div>
                </div>
            `;
            document.getElementById('connectionStatus').id = 'connectionStatus';
            connectionStatus = document.getElementById('connectionStatus');
        });

        function sendMessage() {
            const message = userInput.value.trim();
            if (!message) return;
            if (isWaitingForResponse) return;

            // 添加用户消息
            addMessage(message, 'user');
            userInput.value = '';

            // 显示"正在输入"指示器
            typingIndicator.style.display = 'flex';
            isWaitingForResponse = true;
            sendButton.disabled = true;

            // 滚动到底部
            chatHistory.scrollTop = chatHistory.scrollHeight;

            // 创建AI消息容器
            currentAiMessage = createAiMessage();
            chatHistory.appendChild(currentAiMessage);
            chatHistory.scrollTop = chatHistory.scrollHeight;

            // 发送请求到后端
            fetch('/chat?message=' + encodeURIComponent(message))
                .then(response => {
                    if (!response.ok) {
                        throw new Error('网络响应异常');
                    }
                    return response.text();
                })
                .then(data => {
                    // 更新AI消息内容
                    currentAiMessage.querySelector('.message-content').innerHTML =
                        formatResponse(data);

                    // 隐藏"正在输入"指示器
                    typingIndicator.style.display = 'none';
                    isWaitingForResponse = false;
                    sendButton.disabled = false;

                    // 滚动到底部
                    chatHistory.scrollTop = chatHistory.scrollHeight;
                })
                .catch(error => {
                    console.error('请求错误:', error);
                    currentAiMessage.querySelector('.message-content').innerHTML =
                        '抱歉，处理您的请求时出错。请重试或联系管理员。';
                    typingIndicator.style.display = 'none';
                    isWaitingForResponse = false;
                    sendButton.disabled = false;
                    chatHistory.scrollTop = chatHistory.scrollHeight;
                });
        }

        function createAiMessage() {
            const messageElement = document.createElement('div');
            messageElement.classList.add('message', 'ai-message');

            messageElement.innerHTML = `
                <div class="message-header">
                    <div class="avatar ai-avatar"><i class="fas fa-robot"></i></div>
                    <div>LangChain4J 助手</div>
                </div>
                <div class="message-content">思考中...</div>
            `;

            return messageElement;
        }

        function addMessage(content, sender) {
            const messageElement = document.createElement('div');
            messageElement.classList.add('message', sender + '-message');

            const header = document.createElement('div');
            header.classList.add('message-header');

            const avatar = document.createElement('div');
            avatar.classList.add('avatar', sender + '-avatar');
            avatar.innerHTML = sender === 'user' ? '<i class="fas fa-user"></i>' : '<i class="fas fa-robot"></i>';

            const senderName = document.createElement('div');
            senderName.textContent = sender === 'user' ? '用户' : 'LangChain4J 助手';

            header.appendChild(avatar);
            header.appendChild(senderName);

            const contentElement = document.createElement('div');
            contentElement.classList.add('message-content');
            contentElement.textContent = content;

            messageElement.appendChild(header);
            messageElement.appendChild(contentElement);

            chatHistory.insertBefore(messageElement, typingIndicator);
        }

        function formatResponse(text) {
            // 简单的格式化处理 - 在实际应用中可以使用更复杂的Markdown解析器
            let formatted = text;

            // 代码块处理
            formatted = formatted.replace(/```([\s\S]*?)```/g, '<pre>$1</pre>');

            // 内联代码
            formatted = formatted.replace(/`([^`]+)`/g, '<code>$1</code>');

            // 链接处理
            formatted = formatted.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank">$1</a>');

            // 换行处理
            formatted = formatted.replace(/\n/g, '<br>');

            // 列表处理
            formatted = formatted.replace(/\n\s*-\s+(.*)/g, '<br>- $1');
            formatted = formatted.replace(/\n\s*\*\s+(.*)/g, '<br>* $1');

            return formatted;
        }

        // 设置示例问题
        function setExample(element) {
            userInput.value = element.textContent;
            userInput.focus();
        }

        // 模拟连接状态变化
        setInterval(() => {
            if (Math.random() > 0.1) return;
            const dot = connectionStatus.querySelector('.status-dot');
            if (Math.random() > 0.5) {
                connectionStatus.querySelector('span').textContent = '后端服务连接中...';
                dot.style.background = '#f59e0b';
            } else {
                connectionStatus.querySelector('span').textContent = '已连接到后端服务';
                dot.style.background = 'var(--primary-color)';
            }
        }, 5000);
    </script>
</body>
</html>